package com.dayu.demo.service;

import java.util.ArrayList;
import java.math.BigDecimal;
import java.time.*;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import com.vecspace.utils.Assert;
import com.vecspace.utils.Convert;
import com.vecspace.utils.DateTimeUtil;
import com.vecspace.utils.NumberUtil;
import com.vecspace.utils.TJSON;
import com.vecspace.exception.HException;
import com.vecspace.exception.DBExceptionManager;
import com.vecspace.database.model.PojoManager;
import com.vecspace.data.model.FilterColumn;
import com.vecspace.data.model.ListExBO;
import com.vecspace.database.model.QueryResultAggregation;
import com.vecspace.security.model.LoginContext;
import com.vecspace.constant.AuthTag;
import com.vecspace.framework.sysdata.service.SysDataService;
import com.vecspace.data.model.DataLockState;
import com.dayu.demo.pojo.Department;
import com.dayu.demo.pojo.Employee;
import com.dayu.demo.pojo.EmployeeEx;
import com.dayu.demo.pojo.EmployeeStats;
import com.dayu.demo.dao.EmployeeDao;

/**功能描述 的增、删、改查等业务操作的service类
 * @template dayu-code-builder
 * @author user
 * @reviewer 
 * @createTime 2021-11-25 16:23:48
 * @version 1.0
 */
@Service("demo_employeeService")
public class EmployeeService {
    /** 根据ID查询 员工
     * @param id   主键值
     * @return Employee
     * @throws Exception
     * @author user
     * @reviewer 
     * @createTime 2021-11-25 16:23:48
     */
    public Employee getEmployee(Long id) throws Exception{
        Employee employee = employeeDao.getEmployee(id);
        return employee;
    }



    /**根据 所属部门 获取员工列表
     *
     * @param deptId 所属部门
     * @return
     * @throws Exception
     * @author user
     * @reviewer
     * @createTime 2021-11-25 16:23:48
     */
    public List<Employee> getEmployeeListByDepartment(Long deptId) throws Exception {
        List<Employee> employeeList = employeeDao.getEmployeeListByDept(deptId);
        return employeeList;
    }

    /**根据 所属部门 获取员工记录条数
     *
     * @param deptId  所属部门
     * @return
     * @throws Exception
     * @author user
     * @reviewer
     * @createTime 2021-11-25 16:23:48
     */
    public int getEmployeeCountByDept(Long deptId) throws Exception {
        int rcount = employeeDao.getEmployeeCountByDept(deptId);
        return rcount;
    }

    /**根据属性名获取字段值
     * @param id 记录id
     * @param propName 属性名
     * @return
     * @throws Exception
     * @author user
     * @reviewer
     * @createTime 2021-11-25 16:23:48
     */
    public Object getValueByProp(Long id, String propName) throws Exception {
    	return employeeDao.getValueByProp(id, propName);
    }

    /**根据id更新指定字段的值（根据propName从pojo获取字段名）
     * @param id 记录id
     * @param propName 属性名
     * @param value 属性值
     * @throws Exception
     * @author user
     * @reviewer
     * @createTime 2021-11-25 16:23:48
     */
    public void updateValueByProp(Long id, String propName, Object value) throws Exception {
        Employee employee = employeeDao.getEmployee(id);
        if(employee == null)return;
        checkNotLocked(employee);
    	Object dbVal = value;
    	String[] propNames = new String[]{ "id","deptId","name","idCardType","idCardNumber","sex","birthday","birthplace","mobile","email","jobTitle","education","school","speciality","remarks","ordnum","rowLock" };
    	String[] datePropNames = new String[]{  };
    	String[] numberPropNames = new String[]{ "id","deptId","ordnum","rowLock" };
    	if(ArrayUtils.indexOf(propNames, propName) < 0) throw new HException("属性名不正确:"+propName);
        if(ArrayUtils.indexOf(datePropNames, propName) >= 0 && value != null){
            if(value.getClass().equals(String.class)){
                dbVal = TJSON.convertToObject(LocalDateTime.class, String.format("\"{0}\"", value));
            }
        }
        if(ArrayUtils.indexOf(numberPropNames, propName) >= 0 && value != null){
            if(value.getClass().equals(String.class)){
                if(StringUtils.isNotBlank(value.toString())){
                    dbVal = new BigDecimal(value.toString());
                }else{
                    dbVal = null;
                }
            }
        }
    	employeeDao.updateValueByProp(id, propName, dbVal);
    }

    /***将页面上传入的对象转为持久化对象（如果页面对象是一个新对象，则insert;否则从数据库库查询出已有的对象item2，将传入的值赋值给item2，然后将item2 update到数据库）
     * 根据页面上放置的属性个数，需要对下面的属性设置进行调整。
     * 对于无法在页面上进行修改的属性，不要进行设值。
     * @param item item是由页面传递过来的对象，item中的属性并不完整，对于在页面上没有展示的属性，item中一律会是空值，而数据库中这些属性可以是有值的
     * @return Employee
     * @throws Exception
     * @author user
     * @reviewer 
     * @createTime 2021-11-25 16:23:48
     */
    public Employee saveViewEmployee(Employee item) throws Exception {
        if (item == null){
            return null;
        }
        /*** 下面开始对item对象的页面传值进行校验，如必填项，格式等 ***/
        //Assert.throwz(StringUtils.isNotBlank() , "条件不满足时抛出异常");
        /*** 结束校验 ***/
        
        Employee item2;
        if (NumberUtil.isNotNullZero(item.getId())) {
            /**从数据库中取出原始对象，将从页面传过来的新值赋值给原始对象，并将原始对象再保存到数据库中 **/
            item2 = getEmployee(item.getId());
            if (item2 != null) {
                /*** 将页面上的新值逐一赋值，不在页面上的属性不要进行赋值 ***/
                item2.setDeptId(item.getDeptId());//更新所属部门
                item2.setName(item.getName());//更新姓名
                item2.setIdCardType(item.getIdCardType());//更新证件类型
                item2.setIdCardNumber(item.getIdCardNumber());//更新身份证号
                item2.setSex(item.getSex());//更新性别
                item2.setBirthday(item.getBirthday());//更新出生日期
                item2.setBirthplace(item.getBirthplace());//更新籍贯
                item2.setMobile(item.getMobile());//更新电话
                item2.setEmail(item.getEmail());//更新邮箱
                item2.setJobTitle(item.getJobTitle());//更新岗位
                item2.setEducation(item.getEducation());//更新学历
                item2.setSchool(item.getSchool());//更新毕业学校
                item2.setSpeciality(item.getSpeciality());//更新专业
                item2.setRemarks(item.getRemarks());//更新备注
                item2.setOrdnum(item.getOrdnum());//更新顺序号
                item2.setRowLock(item.getRowLock());//更新锁定状态
                /**end**/
            } else {
                item2 = item;
            }
        }else{ //item是新增加的对象
            item2 = item;
        }
        saveEmployee(item2);
        return item2;
    }

    /** 插入或修改  ，item中的所有属性都会更新到数据库中（包括属性值为null的，也会将null更新到数据库，覆盖之前的值）。
     * @param item    要保存的对象
     * @return void
     * @throws Exception
     * @author user
     * @reviewer 
     * @createTime 2021-11-25 16:23:48
     */
    public void saveEmployee(Employee item) throws Exception{
        if (item == null){
            return;
        }
        /*** 下面开始对item对象进行校验，如逻辑关系等 ***/
        checkNotLocked(item);
        if(item.getDeptId() == null || item.getDeptId().longValue() ==0){
            item.setDeptId(-1L);
        }
        /*** 结束校验 ***/
        LocalDateTime dtime = LocalDateTime.now();
        if (NumberUtil.isNullOrZero(item.getId())) {
            item.setId(null);
            item.setCreateTime(dtime);  //创建时间
            Long loginUserId = LoginContext.getUserId();//创建人
            item.setCreateUser(loginUserId);
        } else {
        }
        try{
            employeeDao.saveEmployee(item);
        }catch(Exception ex){
            //识别并转换数据库约束错误
            Exception ex2 = DBExceptionManager.parseException(ex);
            throw ex2;
        }
    }


    /**修改数据锁定状态
     * @param id 记录id，另-1表示对整表进行锁定
     * @param lockState
     * @param authTag 权限类型，参考 AuthTag
     * @author user
     * @reviewer 
     * @createTime 2021-11-25 16:23:48
     **/
	public void changeLockState(Long id, int lockState, int authTag) throws Exception {
        Assert.throwz(DataLockState.isValidState(lockState), "不是有效的锁定状态："+lockState);
        //权限验证，是否有选项更改锁定状态
        DataLockState.checkAuth(lockState, authTag);
        if(id != null && id > 0) {
            employeeDao.updateValueByProp(id, "rowLock", lockState);
        }
    }


    /**1、自身处于锁定或者归档状态
     * 2、或者受主数据锁定（由表tm_sys_data_lock记录），或者全表被锁定
     * 3、不通过主数据自身的row_lock标记影响（因为主数据自身被锁定，不意味着所有的子表都被锁定）
     * @param employee
     * @throws Exception 
     */
    private void checkNotLocked(Employee employee) throws Exception {
    	
        if(DataLockState.isLockOrArchived(employee.getRowLock())) {
        	throw new HException("本条记录处于锁定状态，不能编辑和删除");
        }
    }

    /** 根据ID删除 
     * @param id    主键值
     * @return void
     * @throws Exception
     * @author user
     * @reviewer 
     * @createTime 2021-11-25 16:23:48
     */
    public void deleteEmployee(Long id) throws Exception{
        Employee employee = employeeDao.getEmployee(id);
        if(employee == null)return;
        checkNotLocked(employee);
        employeeDao.checkReferenced("T_DEMO_EMPLOYEE", id);
        employeeDao.deleteEmployee(id);
    }

    /**根据查询条件获取查询结果（分页查询），同时进行聚合统计查询
     * 
     * @param deptId 所属部门 
     * @param recursion 是否递归查询所有下级数据 
     * @param filterColumns 查询条件（字段和值）
     * @param pageIndex 查询第几页数据（从1开始）
     * @param pageSize 每页数据条数，-1表示不分页
     * @param sortField 排序字段
     * @param sortOrder 排序顺序
     * @return
     * @throws Exception 
     * @author user
     * @reviewer 
     * @createTime 2021-11-25 16:23:48
     */
    public ListExBO<EmployeeEx, Void, EmployeeStats> getEmployeeExListAndStats(Long deptId, boolean recursion, List<FilterColumn> filterColumns,
        int pageIndex, int pageSize, String sortField, String sortOrder) throws Exception{

        if(pageSize > 10000){ //默认限制返回记录数不能超过10000条
            pageSize = 10000;
        }
        if(pageSize < 1){ //底层查询时-1表示不分页，但是为了避免返回海量数据，所以这里强制返回前10000条数据。
            pageSize = 1;
            pageSize = 10000;
        }
        if(sortField == null || sortField.length() == 0){
            //默认排序字段
            sortField = "id";
            sortOrder = "DESC";
        }else {
            //根据属性名获取字段名，则返回自身
            sortField = PojoManager.getColumnName(EmployeeEx.class, sortField, sortField);
        }
        
        //将filterColumns中的ColumnName进行处理，如果值为propName，则替换为ColumnName
        FilterColumn.replaceFilterColumnName(EmployeeEx.class, filterColumns);
             
        QueryResultAggregation<EmployeeEx, EmployeeStats> employeeList = employeeDao.getEmployeeExListAndStats(deptId, recursion, filterColumns, pageIndex, pageSize, sortField, sortOrder);

        //如果需要返回更多的内容，可以基于ListExBO实现自己的子类，然后返回子类对象
        ListExBO<EmployeeEx, Void, EmployeeStats> employeeBOList = ListExBO.newInstance(employeeList.getEntities(), employeeList.getAggregateEntities(), employeeList.getPagination());

        employeeBOList.setAuthTag(AuthTag.All);//模板生成时默认设置为登录用户对此数据拥有最高权限。需要修改为根据权限系统获取权限。
        
        return employeeBOList;
    }

    /** property **/
    @Autowired
    private EmployeeDao employeeDao;
    
    @Autowired
    private SysDataService sysDataService;
}
